package com.zbkj.crmeb.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crmeb.core.utils.RedisUtil;
import com.utils.DateUtil;
import com.zbkj.crmeb.enums.CrowdCharacteristicsConditionEnum;
import com.zbkj.crmeb.enums.CrowdCharacteristicsEnum;
import com.zbkj.crmeb.store.dao.CrowdCharacteristicsOrderDao;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreOrderInfo;
import com.zbkj.crmeb.store.service.CrowdCharacteristicsOrderService;
import com.zbkj.crmeb.store.service.StoreOrderInfoService;
import com.zbkj.crmeb.store.service.StoreUserGroupFeatureService;
import com.zbkj.crmeb.store.service.StoreUserGroupService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实现类
 *
 * @Author: wangzh
 * @Date: 2022/9/28 10:17
 */
@Service
public class CrowdCharacteristicsOrderServiceImpl extends ServiceImpl<CrowdCharacteristicsOrderDao, StoreOrder> implements CrowdCharacteristicsOrderService {

    @Autowired
    StoreUserGroupService storeUserGroupService;
    @Autowired
    StoreUserGroupFeatureService userGroupFeatureService;
    @Autowired
    UserService userService;
    @Autowired
    StoreOrderInfoService storeOrderInfoService;
    @Autowired
    CrowdCharacteristicsOrderDao dao;

    /**
     * 功能描述: 筛选分群条件中，最近多少天有无店铺购买记录的用户
     *
     * @Param: [users, groupId, code, day]
     * @Return: void
     * @Author: wangzh
     * @Date: 2022/9/28 16:24
     */
    @Override
    public void SiftPurchase(List<User> users, Integer groupId, Integer code, Integer day, Integer merId) {

        //最近有购买的用户id集合
        List<Integer> havePurchaseUserIds = getHavePurchaseUserId(day, merId);

        Iterator<User> it = users.iterator();

        //当条件为有购买
        if (Objects.equals(CrowdCharacteristicsEnum.HAVE_PURCHASE.getCode(), code)) {
            //循环删除
            while (it.hasNext()) {
                User user = it.next();
                //当用户不存在于havePurchaseUserIds中，说明最近day天无购买,将其剔除users
                if (!havePurchaseUserIds.contains(user.getUid())) {
                    it.remove();
                    //将user中对应的featureId删除
                    deleteFeatureId(user, groupId);
                }
            }
        }

        //当条件为无购买
        if (Objects.equals(CrowdCharacteristicsEnum.NO_PURCHASE.getCode(), code)) {
            //循环删除
            while (it.hasNext()) {
                User user = it.next();
                //当用户存在于havePurchaseUserIds中，说明最近day天有购买，将其剔除users
                if (havePurchaseUserIds.contains(user.getUid())) {
                    it.remove();
                    //将user中对应的featureId删除
                    deleteFeatureId(user, groupId);
                }
            }
        }
    }

    /**
     * 功能描述: 筛选最近day天有无复购的用户
     *
     * @Param: [request]
     * @Return: void
     * @Author: wangzh
     * @Date: 2022/9/29 11:49
     */
    @Override
    public void SiftRePurchase(List<User> users, Integer groupId, Integer code, Integer day, Integer merId) {

        //筛选有购买记录的用户
        //方法调用结束后，users为最近day天有购买的用户
        SiftPurchase(users, groupId, CrowdCharacteristicsEnum.HAVE_PURCHASE.getCode(), day, merId);

        //用户列表为空
        if (CollectionUtils.isEmpty(users)) {
            return;
        }

        List<Integer> userIds = users.stream().map(User::getUid).collect(Collectors.toList());

        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("uid", "count(*) as total_num")
                .ne("status", 0)
                .ne("status", 5)
                .ge("pay_time", DateUtil.getDaysAgo(day))
                .in("uid", userIds)
                .groupBy("uid");

        List<StoreOrder> storeOrders = this.list(queryWrapper);
        //用户购买次数
        Map<Integer, Integer> userRePurchaseCount = storeOrders.stream().collect(Collectors.toMap(StoreOrder::getUid, StoreOrder::getTotalNum));

        Iterator<User> it = users.iterator();
        while (it.hasNext()) {
            User user = it.next();
            int count = userRePurchaseCount.get(user.getUid());
            //有复购
            if (Objects.equals(CrowdCharacteristicsEnum.WITH_REPURCHASE.getCode(), code)) {
                //订单数大于1，说明最近day天有复购，保留id
                if (count > 1) {
                    continue;
                } else {
                    //否则删除
                    it.remove();
                    deleteFeatureId(user, groupId);
                }
            }
            //无复购
            if (Objects.equals(CrowdCharacteristicsEnum.NO_REPURCHASE.getCode(), code)) {
                if (count > 1) {
                    it.remove();
                    deleteFeatureId(user, groupId);
                }
            }
        }
    }

    /**
     * 功能描述: 筛选符合实付金额的用户
     *
     * @Param: [request]
     * @Return: void
     * @Author: wangzh
     * @Date: 2022/9/29 14:22
     */
    @Override
    public void SiftPayPrice(List<User> users, Integer groupId, Integer code, Integer merId, Integer judgeCondition, Integer conditionOne, Integer conditionTwo) {
        //判断用户列表是否为空
        if (CollectionUtils.isEmpty(users)) {
            return;
        }
        //用户id列表
        String userIds = users.stream().map(User::getUid).map(String::valueOf).collect(Collectors.joining(","));
        List<StoreOrder> reallyPayPriceEntity = dao.getReallyPayPrice(merId, userIds);
        //符合条件的用户id
        List<Integer> userIdsNotFit = new ArrayList<>();
        //每个用户对应的实际支付金额
        Map<Integer, BigDecimal> reallyPayPriceMap = reallyPayPriceEntity.stream().collect(Collectors.toMap(StoreOrder::getUid, StoreOrder::getPayPrice));
        //删选符合用户的id
        for (Integer i : reallyPayPriceMap.keySet()) {
            //小于
            if (Objects.equals(CrowdCharacteristicsConditionEnum.LESS_THAN.getCode(), judgeCondition)) {
                if (reallyPayPriceMap.get(i).compareTo(BigDecimal.valueOf(conditionOne)) <= 0) {
                    userIdsNotFit.add(i);
                }
            }
            //区间
            if (Objects.equals(CrowdCharacteristicsConditionEnum.SECTION.getCode(), judgeCondition)) {
                if (reallyPayPriceMap.get(i).compareTo(BigDecimal.valueOf(conditionOne)) >= 0 && reallyPayPriceMap.get(i).compareTo(BigDecimal.valueOf(conditionTwo)) <= 0) {
                    userIdsNotFit.add(i);
                }
            }
            //大于
            if (Objects.equals(CrowdCharacteristicsConditionEnum.GREATER_THAN.getCode(), judgeCondition)) {
                if (reallyPayPriceMap.get(i).compareTo(BigDecimal.valueOf(conditionOne)) >= 0) {
                    userIdsNotFit.add(i);
                }
            }
        }

        Iterator<User> it = users.iterator();
        //剔除不符合的用户
        while (it.hasNext()) {
            User user = it.next();
            if (!userIdsNotFit.contains(user.getUid())) {
                it.remove();
                deleteFeatureId(user, groupId);
            }
        }
    }

    /**
     * @author: wangzh
     * @date: 2022/9/29 22:05
     * @Description: 筛选实际支付次数符合要求的用户
     */
    @Override
    public void SiftPayTime(List<User> users, Integer groupId, Integer code, Integer merId, Integer judgeCondition, Integer conditionOne, Integer conditionTwo) {
        if (CollectionUtils.isEmpty(users)) {
            return;
        }
        List<Integer> userIds = users.stream().map(User::getUid).collect(Collectors.toList());

        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("count(*) as total_num", "uid")
                .eq("paid", 1)
                .in("uid", userIds)
                .groupBy("uid");
        List<StoreOrder> usersPayTimeStoreOrders = this.list(queryWrapper);
        //符合条件的用户id
        List<Integer> userIdsFit = usersPayTimeStoreOrders.stream().map(StoreOrder::getUid).collect(Collectors.toList());
        Map<Integer, Integer> userPayTimeMap = usersPayTimeStoreOrders.stream().collect(Collectors.toMap(StoreOrder::getUid, StoreOrder::getTotalNum));

        Iterator<User> it = users.iterator();

        while (it.hasNext()) {
            User user = it.next();

            //未匹配到，直接剔除
            if (!userIdsFit.contains(user.getUid())){
                it.remove();
                deleteFeatureId(user, groupId);
                continue;
            }

            //当前用户订单数量
            int count = userPayTimeMap.get(user.getUid());

            //小于，包含0
            if (Objects.equals(CrowdCharacteristicsConditionEnum.LESS_THAN.getCode(), judgeCondition)) {
                //未退款的订单数大于conditionOne，不满足条件，剔除
                if (count > conditionOne) {
                    it.remove();
                    deleteFeatureId(user, groupId);
                }
            }
            //大于
            if (Objects.equals(CrowdCharacteristicsConditionEnum.GREATER_THAN.getCode(), judgeCondition)) {
                //大于0，所有用户都满足
                if (conditionOne == 0) {
                    return;
                }

                //未退款的订单数小于conditionOne，不满足条件，剔除
                if (count < conditionOne) {
                    it.remove();
                    deleteFeatureId(user, groupId);
                }
            }
            //区间
            if (Objects.equals(CrowdCharacteristicsConditionEnum.SECTION.getCode(), judgeCondition)) {
                //不在区间内的进行剔除
                if (count < conditionOne || count > conditionTwo) {
                    it.remove();
                    deleteFeatureId(user, groupId);
                }
            }
        }
    }

    /**
     * 功能描述: 获取day天内有购买行为的用户id
     *
     * @Param: [day]
     * @Return: java.util.List<java.lang.Integer>
     * @Author: wangzh
     * @Date: 2022/9/29 10:04
     */
    public List<Integer> getHavePurchaseUserId(Integer day, Integer merId) {

        List<StoreOrder> storeOrders = this.list(Wrappers.<StoreOrder>lambdaQuery()
                .eq(StoreOrder::getMerId, merId)
                .ne(StoreOrder::getStatus, 0)
                .ne(StoreOrder::getStatus, 5)
                .ge(StoreOrder::getPayTime, DateUtil.getDaysAgo(day))
                .groupBy(StoreOrder::getUid));

        return storeOrders.stream().map(StoreOrder::getUid).collect(Collectors.toList());
    }

    /**
     * 功能描述: 删除用户群组id
     *
     * @Param: [user, groupId]
     * @Return: void
     * @Author: wangzh
     * @Date: 2022/9/29 11:51
     */
    public void deleteFeatureId(User user, Integer groupId) {
        //groupId为0时，仅计算人数，不删除user中对应的groupId
        if (groupId == 0) {
            return;
        }
        //将字符串转化为List
        List<Integer> featureIds = new ArrayList<>();
        if (StringUtils.isNotBlank(user.getFeatureId())) {
            featureIds = Arrays.stream(user.getFeatureId().split(",")).map(Integer::valueOf).collect(Collectors.toList());
        }

        if (featureIds.size() != 0 && featureIds.contains(groupId)) {
            featureIds.remove(groupId);
            String featureIdsString = featureIds.stream().map(String::valueOf).collect(Collectors.joining(","));
            userService.update(new UpdateWrapper<User>().lambda()
                    .eq(User::getUid, user.getUid())
                    .set(User::getFeatureId, featureIdsString));
        }
    }

    public BigDecimal getReallyPrice(List<Integer> orderIds) {
        List<StoreOrderInfo> StoreOrderInfos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                .in(StoreOrderInfo::getOrderId, orderIds));
        //实付金额
        Optional<BigDecimal> payPrice = StoreOrderInfos.stream().map(StoreOrderInfo::getPayPrice).reduce(BigDecimal::add);
        //退款金额
        Optional<BigDecimal> refundPrice = StoreOrderInfos.stream().map(StoreOrderInfo::getRefundPrice).reduce(BigDecimal::add);
        //判断金额
        return payPrice.get().subtract(refundPrice.get());
    }


}
